package juc.popular;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;

/**
 * ThreadLocal的作用是提供线程内的局部变量，这种变量在多线程环境下访问时能够保证各个线程里变量的独立性
 * <p>
 * * {@link ThreadLocal#ThreadLocal()}空参构造
 * * {@link ThreadLocal#withInitial(Supplier)}可以指定一个初始值
 * * {@link ThreadLocal#set(Object)}为当前线程设置变量
 * * {@link ThreadLocal#get()}获取当前线程中的变量
 * * {@link ThreadLocal#remove()}移除当前线程中的变量
 *
 * @author 王霄
 * @date 2021/9/15 11:06
 **/
public class ThreadLocalDemo {

    private record Jock(String name) {
    }

    private static final ThreadLocal<Jock> jockMap = new ThreadLocal<>();
    private static Jock jock;

    public static void main(String[] args) {
        String[] nameArr = {"科比" , "杜兰特" , "乔丹" , "威少" , "螺丝" , "保罗乔治"};
        ExecutorService executor = Executors.newCachedThreadPool();
        Random random = new Random();

        for (int i = 0; i < 10000; i++) {
            //随机一个名称
            String name = nameArr[random.nextInt(6)];

            //TheadLocal不会存在线程安全
            executor.submit(() -> {
                Thread thread = Thread.currentThread();
                thread.setName(name);
                jockMap.set(new Jock(name));
                if (!thread.getName().equals(jockMap.get().name)) {
                    System.out.printf("【%s,%s】%n" , thread.getName(), jockMap.get().name);
                }
                jockMap.remove();
            });

            //共享变量会存在线程安全
            executor.execute(() -> {
                Thread thread = Thread.currentThread();
                thread.setName(name);
                jock = new Jock(name);
                if (!thread.getName().equals(jock.name)) {
                    System.out.printf("[%s,%s]%n" , thread.getName(), jock.name);
                }
            });
        }
    }
}
